package erfgame.core;

import java.util.List;

public class BaseCompositeOperation<C, K, E extends Throwable> extends AbstractOperation<C, E> {
	
	@SuppressWarnings(value="unchecked")
	private static final OperationProgress buildProgress(List<Operation> operations, int currentIndex ) {
		int numSteps = 0;
		int step = 0;
		String name = null;
		for(int i=operations.size(); i>0; ) {
			i--;
			Operation operation = operations.get(i);
			OperationProgress progress = operation.getProgress();
			numSteps += progress.getNumberOfSteps();
			if( i <= currentIndex ) {
				step += progress.getStep();
			}
			if( i == currentIndex ) {
				name = progress.getName();
			}
		}
		return new OperationProgress(step, numSteps, name);
	}
	
	private List<Operation<K,E>> operations;
	private int currentIndex;
	private OperationProgressListener progressListener;
	
	@SuppressWarnings(value="unchecked")
	public BaseCompositeOperation( List<Operation<K,E>> operations ) {
		super(buildProgress((List)operations, 0));
		this.operations = operations;
		this.progressListener = new OperationProgressListener() {
			public void progressUpdated(OperationProgressEvent e) {
				reloadProgress();
			}
		};
		for( int i=operations.size(); i>0; ) {
			i--;
			Operation<K,E> operation = operations.get(i);
			operation.addOperationProgressListener(
					this.progressListener
			);
		}
	}
	
	@SuppressWarnings(value="unchecked")
	protected void reloadProgress() {
		OperationProgress p = buildProgress((List)operations, currentIndex);
		setProgress( p );
	}

	public C perform() throws E {
		C result = createEmpty();
		for(currentIndex=0; currentIndex<this.operations.size(); currentIndex++) {
			Operation<K,E> currentOperation = this.operations.get(currentIndex);
			K currentResult = currentOperation.perform();
			result = compose( result, currentResult );
		}
		return result;
	}
	
	protected C createEmpty() {
		return null;
	}
	
	protected C compose( C into, K result ) {
		return null;
	}
}
